﻿using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using SharpPcap;
using System;
using System.Diagnostics;
using System.Security.Policy;
using PacketDotNet;
using SharpPcap.LibPcap;
using static SharpPcap.LibPcap.Sockaddr;
using System.Collections.ObjectModel;
using System.Net.NetworkInformation;
using System.Net;
using System.Management;
using System.Collections.Generic;
using Net.http;

namespace HBase
{
    public class HATask :ZtTask {
   
        protected override bool HaRun() { 
            return true;
        }
        public override bool excute() {
     

            if (string.IsNullOrWhiteSpace(NetConfig.MeIp)) {
                return true;
            }
            if (NetConfig.MeIp == BaseConfig.MainSiteIp) {
                String url = "http://" + BaseConfig.SlaveSiteIp + ":" + NetConfig.Port + "/open/stop";
                HttpRequestUrl.httpGet(url, false, 5000);
                BaseConfig.Working = true;
                arp();
                consoleOnly(InfoCode.consleOnly_Ha, "当前主ip" + NetConfig.MeIp + "广播" + BaseConfig.VirtualIp);
            } else if (NetConfig.MeIp == BaseConfig.SlaveSiteIp) {
                String url = "http://" + BaseConfig.MainSiteIp + ":" + NetConfig.Port + "/open/running"; ;
                String value = HttpRequestUrl.httpGet(url, false, 5000);
                if (String.IsNullOrWhiteSpace(value)) {
                    arp();
                    consoleOnly(InfoCode.consleOnly_Ha, "当前从ip" + NetConfig.MeIp + "广播"+BaseConfig.VirtualIp);

                } else {
                    BaseConfig.Working = false;
                }
            } else {
                consoleOnly(InfoCode.consleOnly_Ha,"当前ip" + NetConfig.MeIp + "非不是主从服务器" + BaseConfig.MainSiteIp + "or" + BaseConfig.SlaveSiteIp);

            }
        
            return true;
        }



       public void arp() {
            
                myARP(BaseConfig.VirtualIp, getDevice());
           
        }

        protected override bool init() {
            time = 1000;
  
        
            String[] para = p.Split('-');
            BaseConfig.VirtualIp = para[0];
            BaseConfig.MainSiteIp = para[1];
            BaseConfig.SlaveSiteIp = para[2];
    
            LibPcapLiveDevice device = getDevice();
            if (device == null) {
                console(InfoCode.consle_Ha_ip_error, "ha ip 配置异常");
                return false;
            }
            device.Open();
            device.OnPacketArrival += new PacketArrivalEventHandler(device_OnPacketArrival);
            device.StartCapture();
            return true;
        }
        private void device_OnPacketArrival(object sender, RawCapture e) {
            byte[] data = e.Data;

           String result = Convert.ToHexString(data);
          //  console(result);
            if (!BaseConfig.Working) {
                return;
            }
            LibPcapLiveDevice device = (LibPcapLiveDevice)sender;
         
            Packet p = Packet.ParsePacket(e.LinkLayerType, data);
            if (!(p is EthernetPacket)) {
                return;
            }
            EthernetPacket ep = (EthernetPacket)p;
            if (ep.Type == EthernetPacketType.Arp) {
                doArp(device, ep.PayloadPacket as ARPPacket);
            } else if (ep.Type == EthernetPacketType.IpV4) {

            }
        }
        LibPcapLiveDevice getDevice() {
            List<LibPcapLiveDevice> devices = Pcap.Devices( "");
            if (devices.Count < 1) {
                Console.WriteLine("No devices were found on this machine");
                BaseConfig.Working = true;
                return null;
            }

    
            foreach (var dev in devices) {
                LibPcapLiveDevice d = (LibPcapLiveDevice)dev;
                ReadOnlyCollection<PcapAddress> adds = d.Addresses;

                foreach (PcapAddress pcapAddress in adds) {
                    if (pcapAddress.Addr.type == Sockaddr.AddressTypes.AF_INET_AF_INET6 && pcapAddress.Addr.sa_family == Pcap.AF_INET) {//pcapAddress.Addr.sa_family == Pcap.AF_INET
                        IPAddress addr = pcapAddress.Addr.ipAddress;
                        if (addr.ToString() == BaseConfig.MainSiteIp || addr.ToString() == BaseConfig.SlaveSiteIp) {
                            NetConfig.MeIp = addr.ToString();
                            return d;
                        }

                    }
                }
            }
            BaseConfig.Working = true;
            return null;
        }

        void doArp(LibPcapLiveDevice device, ARPPacket packet) {


            IPAddress addr = packet.TargetProtocolAddress;
            if (addr.ToString() == BaseConfig.VirtualIp&& packet.SenderProtocolAddress.ToString()!= BaseConfig.VirtualIp) {//arp回应 告诉请求设备物理地址
                PhysicalAddress desHwAddress = packet.SenderHardwareAddress;
                PhysicalAddress sourceHwAddress = getHW(device);
                if (desHwAddress.ToString() == sourceHwAddress.ToString()) {
                    return;
                }
                var ethernetPacket = new EthernetPacket(sourceHwAddress, desHwAddress, PacketDotNet.EthernetPacketType.Arp);
                ethernetPacket.PayloadPacket = new ARPPacket(ARPOperation.Response, desHwAddress, packet.SenderProtocolAddress, sourceHwAddress, addr);
                byte[] b = ethernetPacket.Bytes;
                device.SendPacket(b);
                Console.WriteLine("arp->" + packet.SenderProtocolAddress.ToString());

            }
        }
      
       

        public  void myARP(string vip , LibPcapLiveDevice device) {
            device.Open();
            PhysicalAddress sourceHwAddress = getHW(device);
            String Data = "FF FF FF FF FF FF 11 11 11 11 11 11 08 06 00 01 08 00 06 04 00 01 11 11 11 11 11 11 22 22 22 22 00 00 00 00 00 00 22 22 22 22";
            byte[] b= StrToArraybyte(Data);
          //  sourceHwAddress= PhysicalAddress.Parse("02-00-4c-4f-4f-50");
            byte[] sb = sourceHwAddress.GetAddressBytes();
            for (int i = 0; i < sb.Length; i++) {
                b[i + 6] = sb[i];
                b[i + 22] = sb[i];
            }
            String[] ip = vip.Split(".");
            for (int i = 0; i < ip.Length; i++) {
                byte b1= (byte)int.Parse(ip[i]);
                b[i + 38] = b1;
                b[i + 28] = b1;
            }
            String bstr = HUtil.ToHexStr(b);
            console(InfoCode.consle_Ha_ARP_broadcast,bstr);
            device.SendPacket(b);
        }
        public static byte[] StrToArraybyte(string str)//字符串转换数组
         {
            string[] array = str.Split(new char[] { ' ' });//以空格分割字符串 并生成数组
            int num = array.Length;
            byte[] array2 = new byte[num];
            for (int i = 0; i < num; i++) {
                var str1 = "0x" + array[i];
                array2[i] = Convert.ToByte(str1, 16); //8 位无符号、16进制转换
            }
            return array2;
        }


        public static PhysicalAddress getHW(LibPcapLiveDevice device) {
            ReadOnlyCollection<PcapAddress> adds = device.Addresses;
            foreach (PcapAddress pcapAddress in adds) {
                if (pcapAddress.Addr.type == AddressTypes.HARDWARE) {//pcapAddress.Addr.sa_family == Pcap.AF_INET
                    return pcapAddress.Addr.hardwareAddress;
                }
            }
            return null;
        }
        static IPAddress getIp(LibPcapLiveDevice device) {
            ReadOnlyCollection<PcapAddress> adds = device.Addresses;
            foreach (PcapAddress pcapAddress in adds) {
                if (pcapAddress.Addr.type == AddressTypes.AF_INET_AF_INET6 && pcapAddress.Addr.sa_family == 2) {//pcapAddress.Addr.sa_family == Pcap.AF_INET
                    return pcapAddress.Addr.ipAddress;


                }
            }
            return null;
        }
    }



}
